package cn.ulyer.core.modules.system.rest;


import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.lang.UUID;
import cn.ulyer.common.annotation.Log;
import cn.ulyer.common.constants.ResultCode;
import cn.ulyer.common.exception.InvalidCodeException;
import cn.ulyer.common.security.LoginUser;
import cn.ulyer.common.utils.Result;
import cn.ulyer.common.utils.SecurityUtil;
import cn.ulyer.common.properties.LoginProperties;
import cn.ulyer.core.secure.service.TokenService;
import com.alibaba.fastjson.JSONObject;
import com.google.code.kaptcha.Producer;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/sysRest")
public class SystemRest {


    final String imagePrefix = "image:";

    @Autowired
    private Producer producer;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private LoginProperties loginProperties;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @GetMapping("/captcha")
    public Result<JSONObject> captchaImage() throws IOException {
        JSONObject data = new JSONObject();
        String text = producer.createText();
        BufferedImage image = producer.createImage(text);
        String uid = UUID.fastUUID().toString();
        FastByteArrayOutputStream byteArrayOutputStream = new FastByteArrayOutputStream();
        ImageIO.write(image,"png",byteArrayOutputStream);
        String base64 = Base64.encode(byteArrayOutputStream.toByteArray());
        byteArrayOutputStream.close();
        redisTemplate.opsForValue().set(imagePrefix+uid,text,loginProperties.getCodeExpire(), TimeUnit.MINUTES);
        data.put("uid",uid);
        data.put("image",base64);
        return Result.ok().data(data);
    }

    @Log(action = "登录")
    @PostMapping("/token")
    public Result<String> token(@Valid @RequestBody LoginModel loginModel, HttpServletRequest request){
        String text = (String) redisTemplate.opsForValue().get(imagePrefix+loginModel.getUid());
        if(!loginModel.code.equals(text)){
            throw new InvalidCodeException("验证码错误");
        }
        Object token  =  tokenService.generatorToken(request);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginModel.getUsername(),loginModel.getPassword());
        Authentication authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        if(!authentication.isAuthenticated()){
            return Result.fail(ResultCode.AUTHORIZE_FAIL);
        }
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        loginUser.setToken((String) token);
        tokenService.store(token,authentication);
        return Result.ok().data(token);
    }


    @RequestMapping("/logout")
    public Result logout(){
        String token = SecurityUtil.getUser().getToken();
        tokenService.remove(token);
        return Result.ok();
    }


    @Getter
    @Setter
    public static class LoginModel{

        @NotBlank(message = "用户名不能为空")
        private String username;

        @NotBlank(message = "密码不能为空")
        private String password;

        @NotBlank(message = "验证码不能为空")
        private String code;

        @NotBlank(message = "验证唯一码不能为空")
        private String uid;

    }

}
